local BattleReportParser = class("BattleReportParser")
local FightConst = require("const.FightConst")
local FightHelper = require("gameLogic.fight.FightHelper")
local FightSequence = require("gameLogic.fightSkill.sequence.FightSequence")
local FightMove = require("gameLogic.fightSkill.sequence.FightMove")
local FightActorAction = require("gameLogic.fightSkill.sequence.FightActorAction")
local FightSkillEffect = require("gameLogic.fightSkill.sequence.FightSkillEffect")
local FightInterval = require("gameLogic.fightSkill.sequence.FightInterval")
local FightParallel = require("gameLogic.fightSkill.sequence.FightParallel")
local FightEvent = require("gameLogic.fightSkill.sequence.FightEvent")
local FightParallel = require("gameLogic.fightSkill.sequence.FightParallel")
local FightCallback = require("gameLogic.fightSkill.sequence.FightCallback")
local FightTimeMove = require("gameLogic.fightSkill.sequence.FightTimeMove")
local BuildHelper = require("gameLogic.fight.BuildHelper")
local AttributeConst = require("const.AttributeConst")

function BattleReportParser:ctor(manager)
    self._manager = manager
end

function BattleReportParser:parse(battleReport)
    self._battleReport = battleReport
    local sequence = FightSequence.new()
    self:_subReportParse(sequence, battleReport.roundBefore)
    self:_subReportParse(sequence, battleReport.actionBefore)
    self:_hurtParse(sequence)
    self:_subReportParse(sequence, battleReport.actionAfter)
    return sequence
end

function BattleReportParser:_hurtParse(sequence)
    local battleReport = self._battleReport
    if not self._battleReport.attackSkillId or not self._battleReport.attackEntity then
        return
    end
    local cfg, name, attackActor, targetActors = self:_collectParam(battleReport)
    sequence:addChild(self:_showSkillName(name))
    local seq1 = self:_parseAction(cfg, attackActor, targetActors)
    sequence:addChild(seq1)
end

-------------------------------------子战报----------------------
function BattleReportParser:_subReportParse(tree, report)
    if not report then
        return
    end
    local parallel = FightParallel.new()
    local battleList = report.battleList or {}
    for i = 1, #battleList do
        local battle = battleList[i]
        printDebug(" BattleReportParser:_parse " .. battle.battleType)
        local battleFunc = self["_parse_" .. battle.battleType]
        if battleFunc then
            local behavior = battleFunc(self, battle)
            parallel:addChild(behavior)
        end
    end
    tree:addChild(parallel)
end

function BattleReportParser:_parse_buff_battle(battle)
    local callback =
        FightCallback.new(
        function()
            local time = self._manager:showBuff(battle)
            return time
        end
    )
    return callback
end

function BattleReportParser:_parse_sheild_battle(battle)
    local callback =
        FightCallback.new(
        function()
            local time = self._manager:showSheild(battle)
            return time
        end
    )
    return callback
end

function BattleReportParser:_parse_die_battle(battle)
    local callback =
        FightCallback.new(
        function()
            local actor = self._manager:findActorbyId(battle.entityId)
            actor:setDie(true)
        end
    )
    return callback
end

function BattleReportParser:_parse_call_battle(battle)
    local callback =
        FightCallback.new(
        function()
            self._manager:callActor(battle)
            return 0.3
        end
    )
    return callback
end

function BattleReportParser:_parse_subhurt_battle(battle)
    local callback =
        FightCallback.new(
        function()
            local time = self:_showSubHurt(battle)
            return time
        end
    )
    return callback
end

function BattleReportParser:_parse_fighteffect_battle(battle)
    local callback =
        FightCallback.new(
        function()
            local actor = self._manager:findActorbyId(battle.entityId)
            local effectText = require("view.fightUI.FightEffectText").new(battle.id, actor)
            return 0.5
        end
    )
    return callback
end

function BattleReportParser:_parse_helpattack_battle(battle)
    local sequence = FightSequence.new()
    self:_subAttack(sequence, battle)
    return sequence
end

function BattleReportParser:_parse_counter_battle(battle)
    local sequence = FightSequence.new()
    self:_subAttack(sequence, battle)
    return sequence
end
------------------------------------------------------------

function BattleReportParser:_subAttack(sequence, battle)
    local actor = self._manager:findActorbyId(battle.entityId)
    local oldPos = actor.transform.position
    local tarActor = self._manager:findActorbyId(battle.beEntityId)
    local move = FightTimeMove.new(actor, tarActor)
    sequence:addChild(move)

    local parallel = FightParallel.new()
    local action = FightActorAction.new(actor, "Attack")
    parallel:addChild(action)
    local sequence1 = FightSequence.new()
    parallel:addChild(sequence1)
    local interval = FightInterval.new(0.3)
    sequence1:addChild(interval)
    local parallel1 = FightParallel.new()
    if battle.element ~= AttributeConst.ELEMENT_TREATMENT then
        local actorAct = FightActorAction.new(tarActor, "Hurt")
        parallel1:addChild(actorAct)
    end
    local eventHurt = FightCallback.new(handler(self, self._dispatchHurtText), {tarActor = tarActor, hurt = battle})
    parallel1:addChild(eventHurt)
    sequence1:addChild(parallel1)
    sequence:addChild(parallel)
    local interval2 = FightInterval.new(0.3)
    sequence:addChild(interval2)
    local move2 = FightMove.new(actor, oldPos)
    sequence:addChild(move2)
end

function BattleReportParser:_showSkillName(name)
    local callback =
        FightCallback.new(
        function()
            local skillName = require("gameLogic.ui.SKillShowName").new(name)
        end
    )
    return callback
end

function BattleReportParser:_collectParam(battleReport)
    local skillId = battleReport.attackSkillId
    local cfg, name = BuildHelper.getShowSkillCfg(skillId)
    local hurts = battleReport.hurts or {}
    local targetActors = {}
    for i = 1, #hurts do
        local actor = self._manager:findActorbyId(hurts[i].entityId)
        local param = {}
        param.actor = actor
        param.hurt = hurts[i]
        table.insert(targetActors, param)
    end
    local attackActor = self._manager:findActorbyId(battleReport.attackEntity)
    return cfg, name, attackActor, targetActors
end

function BattleReportParser:_showBuff(buf)
    local time = self._manager:showBuff(buf)
    return time
end

function BattleReportParser:_showSheild(sheild)
    local time = self._manager:showSheild(sheild)
    return time
end

function BattleReportParser:_showSubHurt(subHurt)
    local actor = self._manager:findActorbyId(subHurt.toEntityId)
    actor:setBloodValue(subHurt.blood, subHurt.maxBlood, subHurt.die)
    local param = FightHelper.generateHurtFly(actor, subHurt)
    G_SignalManager:dispatch(SignalConst.EVENT_FIGHT_HURT_TEXT, param)
    return 0.5
end

function BattleReportParser:_parseAction(cfg, actor, targetActors)
    local showName = cfg.show_name
    local showFunc = self["_" .. showName]
    if showFunc then
        printDebug("技能表现 " .. showName)
        return showFunc(self, cfg, actor, targetActors)
    end
end

function BattleReportParser:_moveAttackShow(actor, sequence, hurt, cfg, tarActor)
    local parallel = FightParallel.new()
    local actorAct = FightActorAction.new(actor, cfg.action)
    parallel:addChild(actorAct)
    self:_subReportParse(parallel, self._battleReport.hurtBefore[tarActor:getId()])
    local sequence1 = FightSequence.new()
    local interval = FightInterval.new(cfg.hit_time)
    sequence1:addChild(interval)
    local parallel2 = FightParallel.new()
    self:_subReportParse(parallel2, self._battleReport.attackTime[tarActor:getId()])
    if hurt.element ~= AttributeConst.ELEMENT_TREATMENT then
        local actorAct2 = FightActorAction.new(tarActor, "Hurt")
        parallel2:addChild(actorAct2)
    end
    local hurtSequence = FightSequence.new()
    local eventHurt = FightCallback.new(handler(self, self._dispatchHurtText), {tarActor = tarActor, hurt = hurt})
    hurtSequence:addChild(eventHurt)
    self:_subReportParse(hurtSequence, self._battleReport.hurtAfter[tarActor:getId()])

    parallel2:addChild(hurtSequence)
    sequence1:addChild(parallel2)
    parallel:addChild(sequence1)
    sequence:addChild(parallel)
end

function BattleReportParser:_SkillMove(cfg, actor, targetActors)
    local manager = self._manager
    local sequence = FightSequence.new()
    self:_subReportParse(sequence, self._battleReport.attackBefore)
    for i = 1, #targetActors do
        local hurt = targetActors[i].hurt
        local tarActor = targetActors[i].actor
        if hurt.resistId and hurt.resistId > 0 then
            local resisActor = manager:findActorbyId(hurt.resistId)
            local pos = resisActor.transform.position
            pos.z = pos.z + FightConst.Z_RATIO[actor:getCamp()]
            local parallel = FightParallel.new()
            local move = FightMove.new(actor, pos)
            parallel:addChild(move)
            local pos2 = resisActor.transform.position
            pos2.z = pos2.z + FightConst.Z_RATIO[actor:getCamp()] * 0.5
            local move2 = FightMove.new(tarActor, pos2)
            parallel:addChild(move2)
            sequence:addChild(parallel)
            self:_moveAttackShow(actor, sequence, hurt, cfg, tarActor)
        else
            local pos = tarActor.transform.position
            pos.z = pos.z + FightConst.Z_RATIO[actor:getCamp()]
            local move = FightMove.new(actor, pos)
            sequence:addChild(move)
            self:_moveAttackShow(actor, sequence, hurt, cfg, tarActor)
        end
    end
    self:_subReportParse(sequence, self._battleReport.attackAfter)
    local myPos = actor.transform.position
    local move = FightMove.new(actor, myPos)
    sequence:addChild(move)
    return sequence
end

function BattleReportParser:_SkillInPlace(cfg, actor, targetActors)
    local manager = self._manager
    local sequence = FightSequence.new()
    self:_farAction(sequence, cfg, actor, targetActors)
    return sequence
end

function BattleReportParser:_SkillMoveCenter(cfg, actor, targetActors)
    local manager = self._manager
    local sequence = FightSequence.new()
    local pos = manager:getCenterPos()
    local move = FightMove.new(actor, pos)
    sequence:addChild(move)
    self:_farAction(sequence, cfg, actor, targetActors)
    local myPos = actor.transform.position
    local move = FightMove.new(actor, myPos)
    sequence:addChild(move)
    return sequence
end

function BattleReportParser:_SkillCall(cfg, actor, targetActors)
    local sequence = FightSequence.new()
    self:_subReportParse(sequence, self._battleReport.attackBefore)
    local parallel = FightParallel.new()
    local action = FightActorAction.new(actor, cfg.action)
    parallel:addChild(action)
    local sequence1 = FightSequence.new()
    local interval = FightInterval.new(cfg.hit_time)
    sequence1:addChild(interval)
    self:_subReportParse(sequence1, self._battleReport.attackAfter)
    parallel:addChild(sequence1)
    sequence:addChild(parallel)
    return sequence
end

function BattleReportParser:_farAction(sequence, cfg, actor, targetActors)
    self:_subReportParse(sequence, self._battleReport.attackBefore)
    if #targetActors > 0 then
        local parallel = FightParallel.new()
        local action = FightActorAction.new(actor, cfg.action)
        parallel:addChild(action)
        for i = 1, #targetActors do
            local hurt = targetActors[i].hurt
            local tarActor = targetActors[i].actor
            if hurt.resistId and hurt.resistId > 0 then
                local actor = self._manager:findActorbyId(hurt.resistId)
                local tarPos = actor.transform.position
                local move = FightMove.new(tarActor, tarPos)
                parallel:addChild(move)
            end
            self:_subReportParse(parallel, self._battleReport.hurtBefore[tarActor:getId()])
        end
        local subSequence = FightSequence.new()
        local interval = FightInterval.new(cfg.hit_time)
        subSequence:addChild(interval)
        local parallel1 = FightParallel.new()
        local skillEffect = FightSkillEffect.new(cfg, targetActors, actor)
        parallel1:addChild(skillEffect)
        for i = 1, #targetActors do
            local hurt = targetActors[i].hurt
            local tarActor = targetActors[i].actor
            self:_subReportParse(parallel1, self._battleReport.attackTime[tarActor:getId()])
            if hurt.element ~= AttributeConst.ELEMENT_TREATMENT then
                local action1 = FightActorAction.new(tarActor, "Hurt")
                parallel1:addChild(action1)
            end
            local hurtSeuence = FightSequence.new()
            parallel1:addChild(hurtSeuence)
            local eventHurt =
                FightCallback.new(handler(self, self._dispatchHurtText), {tarActor = tarActor, hurt = hurt})
            hurtSeuence:addChild(eventHurt)
            self:_subReportParse(hurtSeuence, self._battleReport.hurtAfter[tarActor:getId()])
            if hurt.resistId and hurt.resistId > 0 then
                local pos = tarActor.transform.position
                local move = FightMove.new(tarActor, pos)
                hurtSeuence:addChild(move)
            end
        end
        subSequence:addChild(parallel1)
        parallel:addChild(subSequence)
        sequence:addChild(parallel)
    end
    self:_subReportParse(sequence, self._battleReport.attackAfter)
end

function BattleReportParser:_dispatchHurtText(param)
    local tarActor = param.tarActor
    local hurt = param.hurt
    local flyParam = FightHelper.generateHurtFly(tarActor, hurt)
    G_SignalManager:dispatch(SignalConst.EVENT_FIGHT_HURT_TEXT, flyParam)
    tarActor:setBloodValue(hurt.blood, hurt.maxBlood, hurt.die)
    return 0.5
end

return BattleReportParser
